package com.bee.common.core.jsonview;

import com.bee.common.core.exception.GlobalExceptionHandler;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;

/**
 * Adds support for Jackson's JsonView on methods
 * annotated with a {@link ResponseView} annotation
 * @author martypitt
 *
 */
public class ViewAwareJsonMessageConverter extends
        MappingJackson2HttpMessageConverter {

    private final static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	private static final ObjectMapper mapper = new ObjectMapper();
	
    public ViewAwareJsonMessageConverter()
    {
        super();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
		setObjectMapper(objectMapper);
    }

    @Override
    protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {
        if (object instanceof DataView && ((DataView) object).hasView())
        {
            writeView((DataView) object, outputMessage);
        }else if(object instanceof String){

            try {
                log.debug("obj:  "+object);
                ObjectWriter writer = mapper.writer();
                writer.writeValueAsString(object);
            }
            catch (Exception ex) {
                throw new HttpMessageNotWritableException("Could not write text: " + ex.getMessage(), ex);
            }
        } else {
            super.writeInternal(object, type,outputMessage);
            log.debug("Json to client without View: {}",
                    super.getObjectMapper().writeValueAsString(object));
        }
    }

    protected void writeView(DataView view, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {
        JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
		log.debug("Serializing using view {}", view.getView());
        JsonGenerator jsonGenerator =
        		mapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
        try {
        	mapper.writerWithView(view.getView()).writeValue(jsonGenerator, view.getData());
        	log.debug("Json to client with View {}: {}", view.getView().getCanonicalName(),
        			mapper.writerWithView(view.getView()).writeValueAsString(view.getData()));
        }
        catch (IOException ex) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }
    
}
